using System;
using System.Collections.Generic;

namespace Axe.Collections
{
    [Serializable]
    public class RangeDiapasoneCollection
    {
        private List<RangeDiapasone> Sets = new List<RangeDiapasone>();

        #region public int Size
        public int Size
        {
            get
            {
                int TotalSize = 0;

                foreach(RangeDiapasone range in Sets)
                    TotalSize += range.Size;

                return TotalSize;
            }
        }
        #endregion

        #region public bool Contains(int value)

        public bool Contains(int Value)
        {
            foreach (RangeDiapasone range in Sets)
            {
                if (range.Contains(Value))
                    return true;
            }

            return false;
        }

        #endregion

        #region public bool Remove(int value)

        public bool Remove(int value)
        {
            for (int i = 0; i < Sets.Count; i++)
            {
                RangeDiapasone set = Sets[i];
                if (set.Contains(value))
                {
                    if (set.Size == 1)
                    {
                        Sets.RemoveAt(i);
                    }
                    else
                    {
                        RangeDiapasone[] sets = RangeDiapasone.SplitAndRemove(set, value);
                        Sets.RemoveAt(i);
                        foreach (RangeDiapasone s in sets)
                        {
                            Sets.Add(s);
                        }
                        Optimize();
                    }
                    return true;
                }
            }
            return false;
        }

        #endregion

        #region public void Add(int value)

        public void Add(int value)
        {
            foreach (RangeDiapasone set in Sets)
            {
                if (set.Contains(value))
                    return;

                if (set.CanAdd(value))
                {
                    set.Add(value);
                    //Optimize();
                    return;
                }
            }

            RangeDiapasone newEntry = new RangeDiapasone(value, value);
            Sets.Add(newEntry);
        }

        #endregion

        #region public void Optimize()

        public void Optimize()
        {
            Sets.Sort();

            for (int i = 0; i < Sets.Count - 1; i += 2)
            {
                RangeDiapasone s1 = Sets[i];
                RangeDiapasone s2 = Sets[i + 1];

                if (RangeDiapasone.CanSplice(s1, s2))
                {
                    RangeDiapasone s = RangeDiapasone.Splice(s1, s2);
                    Sets.RemoveAt(i);
                    Sets.RemoveAt(i);
                    Sets.Add(s);
                    Sets.Sort();
                    i = 0;
                }
            }
        }

        #endregion

        #region public void Clear()

        public void Clear()
        {
            Sets.Clear();
        }

        #endregion

        #region public override string ToString()

        public override string ToString()
        {
            string res = "";

            foreach (RangeDiapasone Set in Sets)
            {
                res += Set.ToString() + " ";
            }

            return res;
        }

        #endregion

        public int[] ToArray()
        {
            int i = 0,Size = 0;

            foreach(RangeDiapasone range in Sets)
            {
                Size += range.Size;
            }

            int[] set = new int[Size];
            
            foreach(RangeDiapasone range in Sets)
            {
                range.CopyTo(set,i);
                i += range.Size;
            }

            return set;
        }
    }
}